package com.binzaijun.stock.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.binzaijun.stock.common.AjaxResult;
import com.binzaijun.stock.domain.*;
import com.binzaijun.stock.mapper.StockChangeMapper;
import com.binzaijun.stock.mapper.StockInfoDTOMapper;
import com.binzaijun.stock.mapper.StockInfoMapper;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class StockService {

    @Resource
    private StockInfoDTOMapper stockInfoDTOMapper;

    @Resource
    private StockInfoMapper stockInfoMapper;

    @Resource
    private StockChangeMapper stockChangeMapper;

    @Resource
    private StockDataService stockDataService;

    @Resource
    private ElasticsearchService elasticsearchService;

    /**
     * 根据股票代码获取历史k线数据
     */
    public StockKLineDateDTO getStockKLineBySymbol(String symbol){
        StockKLineDateDTO stockKLineDateDTO = new StockKLineDateDTO();
        stockKLineDateDTO.setStockSymbol(symbol);

        StockInfo oneStockInfo = getOneStockInfo(symbol);
        stockKLineDateDTO.setStockName(oneStockInfo.getStockName());

        // 获取sina 数据 - 使用注入的服务
        List<SinaStock> sinaStockList = stockDataService.getSinaStockData(symbol);
        stockKLineDateDTO.setSinaStockList(sinaStockList);

        return stockKLineDateDTO;
    }

    /**
     * 分页查询
     */
    public Page<StockInfoDTO> selectStockInfoDTO(Long pageNum, Long pageSize, String stockName,
                                                 String orderByColumn, String isAsc) {
        QueryWrapper<StockInfoDTO> queryWrapper = new QueryWrapper<>();

        orderByColumn = StrUtil.toUnderlineCase(orderByColumn);

        if ("asc".equals(isAsc)) {
            queryWrapper.orderByAsc(orderByColumn);
        } else {
            queryWrapper.orderByDesc(orderByColumn);
        }

        if (!stockName.equals("")) {
            queryWrapper.eq("stock_name", stockName);
        }

        Page<StockInfoDTO> page = new Page<>(pageNum, pageSize);
        return stockInfoDTOMapper.selectPage(page, queryWrapper);
    }

    public List<StockInfoDTO> getStockInfoDTOByStockName(String stockName) {
        QueryWrapper<StockInfoDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stock_name", stockName);
        return stockInfoDTOMapper.selectList(queryWrapper);
    }

    public Long isExistStockInfoDTO(String stockSymbol) {
        QueryWrapper<StockInfoDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stock_symbol", stockSymbol);
        return stockInfoDTOMapper.selectCount(queryWrapper);
    }

    public Long isExistStockInfo(String stockSymbol) {
        QueryWrapper<StockInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stock_symbol", stockSymbol);
        return stockInfoMapper.selectCount(queryWrapper);
    }

    /**
     * 新增
     */
    public int addStockInfoDTO(String stockSymbol) {
        StockInfo stockInfo = getOneStockInfo(stockSymbol);
        // 添加 stockInfoDTO 数据
        StockInfoDTO stockInfoDTO = new StockInfoDTO();
        stockInfoDTO.setStockSymbol(stockSymbol);
        // 使用注入的服务构建数据
        stockInfoDTO = stockDataService.constructStockInfoDTO(stockInfoDTO);
        stockInfoDTO.setIndustry(stockInfo.getIndustry());
        stockInfoDTO.setStockName(stockInfo.getStockName());
        stockInfoDTO.setStockSymbol(stockInfo.getStockSymbol());

        // 插入到 stockInfoDTO 表中
        return stockInfoDTOMapper.insert(stockInfoDTO);
    }

    public int delStockInfoDTO(String stockSymbol) {
        QueryWrapper<StockInfoDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stock_symbol", stockSymbol);
        return stockInfoDTOMapper.delete(queryWrapper);
    }

    /**
     * 查询单条 stock_info 数据
     */
    public StockInfo getOneStockInfo(String stockSymbol) {
        QueryWrapper<StockInfo> queryWrapper = new QueryWrapper();
        queryWrapper.eq("stock_symbol", stockSymbol);
        return stockInfoMapper.selectOne(queryWrapper);
    }

    public List<StockInfo> selectStockInfo(List<String> stockSymbolList) {
        QueryWrapper<StockInfo> queryWrapper = new QueryWrapper();
        queryWrapper.in("stock_symbol", stockSymbolList);
        return stockInfoMapper.selectList(queryWrapper);
    }

    /**
     * 查询单条 stock_info_dto 数据
     */
    public List<StockInfoDTO> selectStockInfoDTO() {
        QueryWrapper<StockInfoDTO> queryWrapper = new QueryWrapper();
        return stockInfoDTOMapper.selectList(queryWrapper);
    }

    /**
     * 查询条数 stock_info_dto 数据
     */
    public Long countStockInfoDTO(String stockSymbol) {
        QueryWrapper<StockInfoDTO> queryWrapper = new QueryWrapper();
        queryWrapper.eq("stock_symbol", stockSymbol);
        return stockInfoDTOMapper.selectCount(queryWrapper);
    }

    /**
     * 更新单条 stock_info_dto 数据
     */
    public AjaxResult updateStockInfoDTO(String stockSymbol) {
        StockInfo stockInfo = getOneStockInfo(stockSymbol);
        StockInfoDTO stockInfoDTO = new StockInfoDTO();
        stockInfoDTO.setStockSymbol(stockSymbol);
        // 使用注入的服务构建数据
        stockInfoDTO = stockDataService.constructStockInfoDTO(stockInfoDTO);
        stockInfoDTO.setIndustry(stockInfo.getIndustry());
        stockInfoDTO.setStockName(stockInfo.getStockName());
        stockInfoDTO.setStockSymbol(stockSymbol);

        UpdateWrapper<StockInfoDTO> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("stock_symbol", stockSymbol);
        int update = stockInfoDTOMapper.update(stockInfoDTO, updateWrapper);
        return update == 1 ? AjaxResult.success("更新成功") : AjaxResult.error("更新失败");
    }

    public AjaxResult updateBatchStockInfoDTO(List<StockInfoDTO> stockInfos) {
        stockInfos.stream().forEach(stockInfoDTO -> {
            // 使用注入的服务构建数据
            StockInfoDTO construct = stockDataService.constructStockInfoDTO(stockInfoDTO);
            stockInfoDTOMapper.updateById(construct);
        });
        return AjaxResult.success("更新成功");
    }

    public List<StockInfo> getStockInfoByES(String queryString) {
        // 使用注入的Elasticsearch服务
        SearchResponse searchResponse = elasticsearchService.searchStockInfo(queryString);

        List<StockInfo> stockInfoList = new ArrayList<>();

        if (searchResponse != null) {
            SearchHit[] searchHits = searchResponse.getHits().getHits();

            for (SearchHit hit : searchHits) {
                String sourceAsString = hit.getSourceAsString();
                StockInfo stockInfo = JSONObject.parseObject(sourceAsString, StockInfo.class);
                stockInfoList.add(stockInfo);
            }
        }

        return stockInfoList;
    }

    public List<QtStock> getStockCurrentPrice(List<String> stockSymbol) {
        // 使用注入的服务获取实时价格
        return stockDataService.getStockRealTimePrice(stockSymbol);
    }

    public boolean saveStockChange() {
        // 使用注入的服务获取股票异动数据
        List<StockChange> stockChanges = stockDataService.getStockChangesFromEastMoney(new int[0]);
        return stockChangeMapper.saveOrUpdateBatch(stockChanges);
    }

    /**
     * 策略选股
     */
    public List<String> getStockChangeByPolice(int HJFSnums, int DBMRnums) {
        // 使用注入的服务获取股票异动数据
        List<StockChange> stockChanges = stockDataService.getStockChangesFromEastMoney(new int[0]);

        if (HJFSnums > 0) {
            Map<String, Long> HJFSInfo = stockChanges.stream()
                    .filter(tmp -> "火箭发射".equals(tmp.getChangeType()))
                    .collect(Collectors.groupingBy(StockChange::getStockSymbol, Collectors.counting()))
                    .entrySet().stream()
                    .filter(entry -> entry.getValue() > HJFSnums)
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        }

        // 过滤大笔买入的超过三次的股票名称
        if (DBMRnums > 0) {
            Map<String, Long> DBMRInfo = stockChanges.stream()
                    .filter(tmp -> "大笔买入".equals(tmp.getChangeType()))
                    .collect(Collectors.groupingBy(StockChange::getStockSymbol, Collectors.counting()))
                    .entrySet().stream()
                    .filter(entry -> entry.getValue() >= DBMRnums)
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        }

        return new ArrayList<>();
    }

    public List<StockChange> getAllStockChange(int[] changeType) {
        // 使用注入的服务获取股票异动数据
        List<StockChange> stockChanges = stockDataService.getStockChangesFromEastMoney(changeType);

        return stockChanges.stream().map(tmp -> {
            if ("封涨停板".equals(tmp.getChangeType())) {
                String[] parts = tmp.getInfo().split(",");
                tmp.setPrice(parts[0]);
                tmp.setChangeInfo(parts[1]);
                tmp.setPercent(parts[3]);
            } else if ("打开跌停板".equals(tmp.getChangeType())) {
                String[] parts = tmp.getInfo().split(",");
                tmp.setPrice(parts[0]);
                tmp.setChangeInfo(parts[1]);
                tmp.setPercent(parts[1]);
            } else if ("封跌停板".equals(tmp.getChangeType())) {
                String[] parts = tmp.getInfo().split(",");
                tmp.setPrice(parts[0]);
                tmp.setChangeInfo(parts[1]);
                tmp.setPercent(parts[3]);
            } else if ("打开涨停板".equals(tmp.getChangeType())) {
                String[] parts = tmp.getInfo().split(",");
                tmp.setPrice(parts[0]);
                tmp.setChangeInfo(parts[1]);
                tmp.setPercent(parts[1]);
            } else {
                String[] parts = tmp.getInfo().split(",");
                tmp.setPrice(parts[1]);
                tmp.setChangeInfo(parts[0]);
                tmp.setPercent(parts[2]);
            }
            return tmp;
        }).collect(Collectors.toList());
    }
}